<html id="html">
<head>
    <meta charset="UTF-8">
    <style>
        body {
            color: white;
            background: black;
            font-family: sans-serif;
        }

        .hide {
            display: none;
        }

        #loading {
            margin-top: 1em;
        }

        #loading img {
            width: 130px;
            display: block;
            margin: 30px auto;
            animation: spin 10s ease-in-out infinite;
        }

        h1 {
            text-align: center;
        }

        #info {
            position: sticky;
            top: 1rem;
            z-index: 1;
            margin: 1rem;
            float: right;
            font-size: 16pt;
            padding: 0.5rem;
            border: 1px solid #111;
        }

        canvas {
            position: absolute;
            cursor: pointer;
        }

        @keyframes spin {
            50% { transform:scale(150%); }
            100% { transform:scale(100%); }
        }
    </style>
</head>
<body>
<pre id="info" class="hide"></pre>
<h1 id="fail-message" class="hide">Data not load</h1>
<div id="loading">
    <img src="https://presentations.clickhouse.com/images/logo.svg">
    <h1>Loading (~10 seconds, ~20 MB)</h1>
</div>
<canvas id="canvas"></canvas>
<script type="text/javascript">
let start_date = '2021-12-01';
const canvasNode = document.getElementById('canvas');
const infoNode = document.getElementById('info');
const loadingNode = document.getElementById('loading');
const failMessageNode = document.getElementById('fail-message');

let render_data_query = `
    WITH '${start_date}'::Date AS start_date
    SELECT groupArray([d, n, fail]) FROM
    (
        SELECT n, check_start_time::Date - start_date AS d, max(test_status LIKE 'F%' OR test_status LIKE 'E%') AS fail
        FROM checks

        INNER JOIN
        (
            SELECT test_name, toUInt16(row_number() OVER (ORDER BY test_name)) AS n FROM
            (
                SELECT DISTINCT test_name
                FROM checks
                WHERE match(test_name, '^\\d+_') AND check_name ILIKE '%stateless%' AND check_start_time > now() - INTERVAL 1 DAY
            )
        ) AS nums

        USING (test_name)

        WHERE
            check_name ILIKE '%stateless%'
            AND pull_request_number = 0
            AND check_start_time >= start_date
        GROUP BY d, n
        ORDER BY d, n
    )
    FORMAT TSV`;

let test_names_query = `
    SELECT test_name, toUInt16(row_number() OVER (ORDER BY test_name)) AS n FROM
    (
        SELECT DISTINCT test_name
        FROM checks
        WHERE match(test_name, '^\\d+_') AND check_name ILIKE '%stateless%' AND check_start_time > now() - INTERVAL 1 DAY
    ) FORMAT JSONCompact`;

(async () => {
    try {
        const [render_data, test_names_data]  = await Promise.all([
            loadDataByQuery(render_data_query),
            loadDataByQuery(test_names_query),
        ]);

        renderResponse(render_data);
        saveTestNames(test_names_data);
    } catch (e) {
        alert(e);
        showFailMessage();
    } finally {
        hideLoader();
    }
})()

async function loadDataByQuery(query) {
    const response = await fetch(
        "https://play.clickhouse.com?user=play&add_http_cors_header=1",
        { method: "POST", body: query }
    )
    if (!response.ok) throw new Error(`Data download failed\nHTTP status ${response.status}`);
    const json = await response.json();
    return json;
}

function renderResponse(data) {
    const last_pixel = data[data.length - 1];
    canvasNode.width = last_pixel[0] + 1;
    canvasNode.height = last_pixel[1] + 1;

    document.getElementById('html').style.height = canvasNode.height + 10 + 'px';
    document.body.style.height = canvasNode.height + 10 + 'px';

    let ctx = canvasNode.getContext('2d');
    let image = ctx.createImageData(canvasNode.width, canvasNode.height);
    let {data: pixels} = image;

    data.map(elem => {
        let x = elem[0];
        let y = canvasNode.height - elem[1];

        pixels[(x + y * canvasNode.width) * 4 + 0] = elem[2] ? 255 : 0; // r
        pixels[(x + y * canvasNode.width) * 4 + 1] = elem[2] ? 0 : 100; // g
        pixels[(x + y * canvasNode.width) * 4 + 2] = 0; // b
        pixels[(x + y * canvasNode.width) * 4 + 3] = 255; // a
    });

    ctx.putImageData(image, 0, 0);
}

function saveTestNames(data) {
    let {data: test_names} = data;

    canvasNode.addEventListener('mousemove', (event) => {
        infoNode.style.display = 'block';

        const x = event.layerX;
        const y = event.layerY;

        let date = new Date(start_date);
        date.setDate(date.getDate() + x);
        [date] = date.toISOString().split('T');
        let [test] = test_names[canvasNode.height - y];
        let {data: pixel} = canvasNode.getContext('2d').getImageData(x, y, 1, 1);

        updateInfo(date, test, pixel);
    })
}

function updateInfo(date, test, pixel) {
    infoNode.innerText = `${date}, ${test}`;
    infoNode.style.background = pixel[0] > 0 ? '#F00' : (pixel[3] > 0 ? '#006400' : '#000');
}

function hideLoader() {
    loadingNode.style.display = 'none';
}

function showFailMessage() {
    failMessageNode.style.display = 'block';
}

</script>
</body>
</html>
